Skip to content

Add: automatic AICPU architecture defaults (a2a3/a5) - #1521

Merged
ChaoZheng109 merged 1 commit into
hw-native-sys:mainfrom
yanghaoran29:aicpu-pg-a2a3-a5
Aug 3, 2026
Merged

Add: automatic AICPU architecture defaults (a2a3/a5)#1521
ChaoZheng109 merged 1 commit into
hw-native-sys:mainfrom
yanghaoran29:aicpu-pg-a2a3-a5

Conversation

@yanghaoran29

@yanghaoran29 yanghaoran29 commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Summary

aicpu_thread_num no longer needs to be specified by default. A value of 0
is the automatic sentinel, while explicit per-run values remain supported.

  • a2a3 resolves auto to 4 active AICPU threads.
  • a5 resolves auto to 5 active AICPU threads.
  • Onboard runners keep affinity, launch, Runtime, and DFX counts consistent
    with the selected architecture default or explicit override, and require at
    least one orchestration thread plus one scheduler thread.
  • Simulation does not probe hardware topology; it resolves auto directly to
    the architecture default.
  • a5 host topology reconstruction excludes the SMT physical core reserved by
    the AICPU OS so its launch pool matches device-visible availability.
  • Scene tests and examples no longer need fixed aicpu_thread_num entries;
    callers can still provide an explicit value in [2, PLATFORM_MAX].

Validation

  • python -m pytest tests/ut/py/test_chip_worker.py -q — 26 passed
  • C++ no-hardware unit tests — 74 passed
  • a2a3sim vector example — passed
  • a5sim vector example — passed
  • pre-commit run --hook-stage commit — passed

@coderabbitai

coderabbitai Bot commented Jul 27, 2026

Copy link
Copy Markdown

Review Change Stack

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 2acc8255-aa10-44a5-ab13-e2964b6a2143

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

AICPU thread configuration now uses 0 as an auto sentinel, resolves platform defaults against probed usable cores, and writes the effective count back to runtime state. Examples and tests remove fixed aicpu_thread_num: 4 overrides, while documentation and default-value assertions are updated.

Changes

AICPU auto-resolution

Layer / File(s) Summary
Auto configuration contract
src/common/task_interface/call_config.h, src/common/platform/..., simpler_setup/scene_test.py
aicpu_thread_num=0 is accepted as auto, resolved against usable AICPU capacity, and validated with the updated range and failure rules.
Platform launch integration
src/a2a3/platform/..., src/a5/platform/..., src/*/docs/hardware.md
A2A3 and A5 define platform defaults, probe and clamp usable AICPU counts, recalculate scheduler counts, update runtime state, and document the resulting behavior.
Test and example migration
examples/*, tests/st/*, tests/ut/py/*, tests/task_timing/*
Fixed per-case and worker-level aicpu_thread_num: 4 overrides are removed while workload parameters, test flows, and validations remain unchanged.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant TestCase
  participant DeviceRunner
  participant TopologyProbe
  participant Runtime
  TestCase->>DeviceRunner: submit config with aicpu_thread_num=0
  DeviceRunner->>TopologyProbe: probe usable AICPU cores
  TopologyProbe-->>DeviceRunner: return usable count
  DeviceRunner->>Runtime: write resolved thread count
  Runtime-->>TestCase: launch with resolved configuration
Loading

Possibly related PRs

Poem

A bunny hopped through cores so bright,
Let zero choose the threads just right.
Fixed fours now fade from every test,
Probed pools clamp the launch request.
“Auto!” the rabbit cheered with glee—
Runtime threads now grow with me.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 18.18% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly summarizes the main change: automatic AICPU architecture defaults for a2a3 and a5.
Description check ✅ Passed The description is directly related to the changes and explains automatic selection, architecture defaults, clamping, simulation behavior, and validation.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@yanghaoran29
yanghaoran29 force-pushed the aicpu-pg-a2a3-a5 branch 3 times, most recently from 3a46dec to 0f7adad Compare July 27, 2026 07:11

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/a2a3/platform/onboard/host/device_runner.cpp`:
- Around line 330-337: Keep the resolved AICPU count consistent across runtime
and launch/setup state: in src/a2a3/platform/onboard/host/device_runner.cpp
lines 330-337, propagate resolved_aicpu to launch_aicpu_num or use the updated
Runtime getter for subsequent calls; in
src/a2a3/platform/sim/host/device_runner.cpp lines 234-239 and
src/a5/platform/sim/host/device_runner.cpp lines 217-222, write each resolved
fallback value back via runtime.set_aicpu_thread_num(...).

In `@src/a2a3/platform/sim/host/device_runner.cpp`:
- Around line 234-239: After resolving the zero-value fallback in the launch
flow, write the resulting launch_aicpu_num back to the Runtime object before it
is passed to AICPU execution and setup. Update the existing runtime thread-count
state used by get_aicpu_thread_num(), while preserving configured nonzero values
and the PLATFORM_DEFAULT_AICPU_THREAD_NUM fallback.

In `@src/a5/platform/onboard/host/device_runner.cpp`:
- Around line 159-163: Update the launch_aicpu_num normalization in the device
runner to treat only aicpu_thread_num equal to zero as auto; preserve negative
values so validate_launch_aicpu_num() rejects them instead of converting them to
PLATFORM_DEFAULT_AICPU_THREAD_NUM.
- Around line 159-163: After the AICPU resolution logic that computes
resolved_aicpu, update Runtime unconditionally via
runtime.set_aicpu_thread_num(resolved_aicpu). Place this after the allowed-CPU
clamping path so both configured and auto modes publish the effective active
count, including when no adjustment branch is taken.

In `@src/a5/platform/sim/host/device_runner.cpp`:
- Around line 217-222: After resolving the platform default in the launch setup,
write the resulting launch_aicpu_num back through the Runtime setter so
runtime.get_aicpu_thread_num() matches the count used by init_l2_swimlane and
AICPU execution. Keep the existing explicit-count behavior unchanged.

In `@src/common/platform/onboard/host/device_runner_base.cpp`:
- Around line 1168-1174: Update the clamp warning in the thread-count
calculation to log desired instead of requested, so auto mode reports the
architecture default selected by the desired calculation. Preserve the existing
warning text, usable count, and scheduler count.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 8a54c647-7f3b-42da-ab4b-d4cd2bea8eac

📥 Commits

Reviewing files that changed from the base of the PR and between ae29a2c and 0f7adad.

📒 Files selected for processing (92)
  • examples/a2a3/tensormap_and_ringbuffer/benchmark_bgemm/test_benchmark_bgemm.py
  • examples/a2a3/tensormap_and_ringbuffer/merge_pipeline_barrier/test_merge_pipeline_barrier.py
  • examples/a2a3/tensormap_and_ringbuffer/paged_attention/test_paged_attention.py
  • examples/a2a3/tensormap_and_ringbuffer/paged_attention_manual_scope/test_paged_attention.py
  • examples/a2a3/tensormap_and_ringbuffer/paged_attention_ringbuffer/test_paged_attention_ringbuffer.py
  • examples/a2a3/tensormap_and_ringbuffer/paged_attention_unroll_manual_scope/test_paged_attention_unroll.py
  • examples/a2a3/tensormap_and_ringbuffer/qwen3_14b_decode/test_qwen3_14b_decode.py
  • examples/a2a3/tensormap_and_ringbuffer/scalar_data_test/test_scalar_data.py
  • examples/a2a3/tensormap_and_ringbuffer/vector_example/test_vector_example.py
  • examples/a5/tensormap_and_ringbuffer/bgemm/test_bgemm.py
  • examples/a5/tensormap_and_ringbuffer/paged_attention/test_paged_attention.py
  • examples/a5/tensormap_and_ringbuffer/paged_attention_manual_scope/test_paged_attention.py
  • examples/a5/tensormap_and_ringbuffer/paged_attention_unroll_manual_scope/test_paged_attention_unroll.py
  • examples/a5/tensormap_and_ringbuffer/vector_example/test_vector_example.py
  • python/simpler/task_interface.py
  • simpler_setup/scene_test.py
  • src/a2a3/docs/hardware.md
  • src/a2a3/platform/include/common/platform_config.h
  • src/a2a3/platform/onboard/host/device_runner.cpp
  • src/a2a3/platform/sim/host/device_runner.cpp
  • src/a5/docs/hardware.md
  • src/a5/platform/include/common/platform_config.h
  • src/a5/platform/onboard/host/device_runner.cpp
  • src/a5/platform/sim/host/device_runner.cpp
  • src/common/platform/onboard/host/device_runner_base.cpp
  • src/common/platform/onboard/host/device_runner_base.h
  • src/common/platform/sim/host/device_runner_base.cpp
  • src/common/task_interface/call_config.h
  • tests/st/a2a3/host_build_graph/available_aicore_counts/test_available_aicore_counts.py
  • tests/st/a2a3/host_build_graph/bgemm/test_bgemm.py
  • tests/st/a2a3/host_build_graph/dfx/dep_gen/test_dep_gen.py
  • tests/st/a2a3/host_build_graph/dump_args/test_dump_args_example.py
  • tests/st/a2a3/host_build_graph/matmul/test_matmul.py
  • tests/st/a2a3/host_build_graph/paged_attention/test_paged_attention.py
  • tests/st/a2a3/host_build_graph/prepared_callable/test_prepared_callable.py
  • tests/st/a2a3/host_build_graph/run_stream_reuse/test_run_stream_reuse.py
  • tests/st/a2a3/host_build_graph/vector_example/test_vector_example.py
  • tests/st/a2a3/tensormap_and_ringbuffer/alternating_matmul_add/test_alternating_matmul_add.py
  • tests/st/a2a3/tensormap_and_ringbuffer/available_aicore_counts/test_available_aicore_counts.py
  • tests/st/a2a3/tensormap_and_ringbuffer/batch_paged_attention/test_batch_paged_attention.py
  • tests/st/a2a3/tensormap_and_ringbuffer/dfx/args_dump/test_args_dump.py
  • tests/st/a2a3/tensormap_and_ringbuffer/dfx/dep_gen/test_dep_gen.py
  • tests/st/a2a3/tensormap_and_ringbuffer/dfx/l2_swimlane/test_l2_swimlane.py
  • tests/st/a2a3/tensormap_and_ringbuffer/dfx/l2_swimlane/test_l2_swimlane_mixed.py
  • tests/st/a2a3/tensormap_and_ringbuffer/dfx/pmu/test_pmu.py
  • tests/st/a2a3/tensormap_and_ringbuffer/dfx/scope_stats/test_scope_stats.py
  • tests/st/a2a3/tensormap_and_ringbuffer/dynamic_register/test_dynamic_register.py
  • tests/st/a2a3/tensormap_and_ringbuffer/fanin_lookup_perf/test_fanin_lookup_perf.py
  • tests/st/a2a3/tensormap_and_ringbuffer/mixed_example/test_mixed_example.py
  • tests/st/a2a3/tensormap_and_ringbuffer/multi_round_paged_attention/test_multi_round_paged_attention.py
  • tests/st/a2a3/tensormap_and_ringbuffer/orch_so_cache/test_orch_so_cache.py
  • tests/st/a2a3/tensormap_and_ringbuffer/paged_attention_unroll/test_paged_attention_unroll.py
  • tests/st/a2a3/tensormap_and_ringbuffer/paged_attention_unroll_4dims/test_paged_attention_unroll_4dims.py
  • tests/st/a2a3/tensormap_and_ringbuffer/prepared_callable/test_prepared_callable.py
  • tests/st/a2a3/tensormap_and_ringbuffer/spmd_basic/test_spmd_basic.py
  • tests/st/a2a3/tensormap_and_ringbuffer/spmd_batch_dispatch_oob/test_spmd_batch_dispatch_oob.py
  • tests/st/a2a3/tensormap_and_ringbuffer/spmd_multiblock_aiv/test_spmd_multiblock_aiv.py
  • tests/st/a2a3/tensormap_and_ringbuffer/spmd_multiblock_mix/test_spmd_multiblock_mix.py
  • tests/st/a2a3/tensormap_and_ringbuffer/spmd_paged_attention/test_spmd_paged_attention.py
  • tests/st/a2a3/tensormap_and_ringbuffer/spmd_paged_attention_highperf/test_spmd_paged_attention_highperf.py
  • tests/st/a2a3/tensormap_and_ringbuffer/spmd_starvation/test_spmd_starvation.py
  • tests/st/a2a3/tensormap_and_ringbuffer/spmd_sync_start/test_spmd_sync_start.py
  • tests/st/a2a3/tensormap_and_ringbuffer/spmd_sync_start_aiv/test_spmd_sync_start_aiv.py
  • tests/st/a2a3/tensormap_and_ringbuffer/spmd_sync_start_early_dispatch/test_spmd_sync_start_early_dispatch.py
  • tests/st/a2a3/tensormap_and_ringbuffer/spmd_sync_start_edge/test_spmd_sync_start_edge.py
  • tests/st/a2a3/tensormap_and_ringbuffer/spmd_sync_start_stress/test_spmd_sync_start_stress.py
  • tests/st/a2a3/tensormap_and_ringbuffer/test_l3_dependency.py
  • tests/st/a2a3/tensormap_and_ringbuffer/test_l3_group.py
  • tests/st/a5/tensormap_and_ringbuffer/available_aicore_counts/test_available_aicore_counts.py
  • tests/st/a5/tensormap_and_ringbuffer/dfx/args_dump/test_args_dump.py
  • tests/st/a5/tensormap_and_ringbuffer/dfx/dep_gen/test_dep_gen.py
  • tests/st/a5/tensormap_and_ringbuffer/dfx/l2_swimlane/test_l2_swimlane.py
  • tests/st/a5/tensormap_and_ringbuffer/dfx/l2_swimlane/test_l2_swimlane_mixed.py
  • tests/st/a5/tensormap_and_ringbuffer/dfx/pmu/test_pmu.py
  • tests/st/a5/tensormap_and_ringbuffer/dfx/scope_stats/test_scope_stats.py
  • tests/st/a5/tensormap_and_ringbuffer/mixed_example/test_mixed_example.py
  • tests/st/a5/tensormap_and_ringbuffer/orch_so_cache/test_orch_so_cache.py
  • tests/st/a5/tensormap_and_ringbuffer/paged_attention_unroll/test_paged_attention_unroll.py
  • tests/st/a5/tensormap_and_ringbuffer/prepared_callable/test_prepared_callable.py
  • tests/st/a5/tensormap_and_ringbuffer/simt_basic/test_simt_basic.py
  • tests/st/a5/tensormap_and_ringbuffer/spmd_basic/test_spmd_basic.py
  • tests/st/a5/tensormap_and_ringbuffer/spmd_multiblock_aiv/test_spmd_multiblock_aiv.py
  • tests/st/a5/tensormap_and_ringbuffer/spmd_multiblock_mix/test_spmd_multiblock_mix.py
  • tests/st/a5/tensormap_and_ringbuffer/spmd_starvation/test_spmd_starvation.py
  • tests/st/a5/tensormap_and_ringbuffer/spmd_sync_start/test_spmd_sync_start.py
  • tests/st/a5/tensormap_and_ringbuffer/spmd_sync_start_aiv/test_spmd_sync_start_aiv.py
  • tests/st/a5/tensormap_and_ringbuffer/spmd_sync_start_early_dispatch/test_spmd_sync_start_early_dispatch.py
  • tests/st/a5/tensormap_and_ringbuffer/spmd_sync_start_edge/test_spmd_sync_start_edge.py
  • tests/st/a5/tensormap_and_ringbuffer/spmd_sync_start_mix_spill/test_spmd_sync_start_mix_spill.py
  • tests/st/a5/tensormap_and_ringbuffer/spmd_sync_start_stress/test_spmd_sync_start_stress.py
  • tests/st/task_timing/task_timing_slots/test_task_timing_e2e.py
  • tests/ut/py/test_chip_worker.py
💤 Files with no reviewable changes (72)
  • tests/st/a5/tensormap_and_ringbuffer/spmd_starvation/test_spmd_starvation.py
  • examples/a2a3/tensormap_and_ringbuffer/benchmark_bgemm/test_benchmark_bgemm.py
  • tests/st/a2a3/tensormap_and_ringbuffer/alternating_matmul_add/test_alternating_matmul_add.py
  • examples/a2a3/tensormap_and_ringbuffer/merge_pipeline_barrier/test_merge_pipeline_barrier.py
  • examples/a5/tensormap_and_ringbuffer/vector_example/test_vector_example.py
  • tests/st/a2a3/tensormap_and_ringbuffer/dfx/l2_swimlane/test_l2_swimlane.py
  • tests/st/a5/tensormap_and_ringbuffer/mixed_example/test_mixed_example.py
  • examples/a2a3/tensormap_and_ringbuffer/scalar_data_test/test_scalar_data.py
  • tests/st/a5/tensormap_and_ringbuffer/spmd_sync_start_aiv/test_spmd_sync_start_aiv.py
  • tests/st/a5/tensormap_and_ringbuffer/spmd_multiblock_aiv/test_spmd_multiblock_aiv.py
  • tests/st/a5/tensormap_and_ringbuffer/spmd_sync_start/test_spmd_sync_start.py
  • tests/st/a5/tensormap_and_ringbuffer/available_aicore_counts/test_available_aicore_counts.py
  • tests/st/a5/tensormap_and_ringbuffer/dfx/pmu/test_pmu.py
  • tests/st/a2a3/tensormap_and_ringbuffer/spmd_sync_start/test_spmd_sync_start.py
  • tests/st/a2a3/tensormap_and_ringbuffer/spmd_sync_start_aiv/test_spmd_sync_start_aiv.py
  • tests/st/a2a3/tensormap_and_ringbuffer/available_aicore_counts/test_available_aicore_counts.py
  • tests/st/a5/tensormap_and_ringbuffer/dfx/args_dump/test_args_dump.py
  • tests/st/a5/tensormap_and_ringbuffer/dfx/l2_swimlane/test_l2_swimlane.py
  • examples/a2a3/tensormap_and_ringbuffer/paged_attention_ringbuffer/test_paged_attention_ringbuffer.py
  • tests/st/a2a3/tensormap_and_ringbuffer/spmd_starvation/test_spmd_starvation.py
  • tests/st/a5/tensormap_and_ringbuffer/spmd_basic/test_spmd_basic.py
  • tests/st/a5/tensormap_and_ringbuffer/dfx/l2_swimlane/test_l2_swimlane_mixed.py
  • tests/st/a2a3/tensormap_and_ringbuffer/spmd_multiblock_mix/test_spmd_multiblock_mix.py
  • tests/st/a2a3/host_build_graph/bgemm/test_bgemm.py
  • tests/st/a5/tensormap_and_ringbuffer/prepared_callable/test_prepared_callable.py
  • tests/st/a5/tensormap_and_ringbuffer/spmd_sync_start_early_dispatch/test_spmd_sync_start_early_dispatch.py
  • tests/st/a5/tensormap_and_ringbuffer/dfx/scope_stats/test_scope_stats.py
  • tests/st/a2a3/tensormap_and_ringbuffer/dfx/scope_stats/test_scope_stats.py
  • tests/st/a2a3/host_build_graph/vector_example/test_vector_example.py
  • tests/st/a2a3/tensormap_and_ringbuffer/spmd_sync_start_early_dispatch/test_spmd_sync_start_early_dispatch.py
  • examples/a2a3/tensormap_and_ringbuffer/qwen3_14b_decode/test_qwen3_14b_decode.py
  • tests/st/a5/tensormap_and_ringbuffer/spmd_sync_start_mix_spill/test_spmd_sync_start_mix_spill.py
  • tests/st/a2a3/tensormap_and_ringbuffer/dfx/l2_swimlane/test_l2_swimlane_mixed.py
  • tests/st/a5/tensormap_and_ringbuffer/paged_attention_unroll/test_paged_attention_unroll.py
  • tests/st/a2a3/host_build_graph/matmul/test_matmul.py
  • examples/a2a3/tensormap_and_ringbuffer/vector_example/test_vector_example.py
  • tests/st/a2a3/tensormap_and_ringbuffer/spmd_sync_start_edge/test_spmd_sync_start_edge.py
  • tests/st/a2a3/host_build_graph/available_aicore_counts/test_available_aicore_counts.py
  • tests/st/a2a3/tensormap_and_ringbuffer/dfx/args_dump/test_args_dump.py
  • tests/st/a2a3/tensormap_and_ringbuffer/spmd_sync_start_stress/test_spmd_sync_start_stress.py
  • tests/st/a2a3/tensormap_and_ringbuffer/spmd_batch_dispatch_oob/test_spmd_batch_dispatch_oob.py
  • examples/a2a3/tensormap_and_ringbuffer/paged_attention_unroll_manual_scope/test_paged_attention_unroll.py
  • tests/st/a2a3/tensormap_and_ringbuffer/multi_round_paged_attention/test_multi_round_paged_attention.py
  • tests/st/a2a3/host_build_graph/prepared_callable/test_prepared_callable.py
  • tests/st/a2a3/tensormap_and_ringbuffer/dfx/pmu/test_pmu.py
  • tests/st/a5/tensormap_and_ringbuffer/spmd_sync_start_stress/test_spmd_sync_start_stress.py
  • examples/a5/tensormap_and_ringbuffer/paged_attention_manual_scope/test_paged_attention.py
  • tests/st/a5/tensormap_and_ringbuffer/spmd_multiblock_mix/test_spmd_multiblock_mix.py
  • tests/st/a2a3/host_build_graph/dump_args/test_dump_args_example.py
  • tests/st/a2a3/tensormap_and_ringbuffer/paged_attention_unroll/test_paged_attention_unroll.py
  • examples/a2a3/tensormap_and_ringbuffer/paged_attention/test_paged_attention.py
  • tests/st/a2a3/host_build_graph/paged_attention/test_paged_attention.py
  • tests/st/a2a3/tensormap_and_ringbuffer/dfx/dep_gen/test_dep_gen.py
  • tests/st/a2a3/tensormap_and_ringbuffer/mixed_example/test_mixed_example.py
  • examples/a5/tensormap_and_ringbuffer/bgemm/test_bgemm.py
  • tests/st/a2a3/tensormap_and_ringbuffer/paged_attention_unroll_4dims/test_paged_attention_unroll_4dims.py
  • tests/st/a2a3/tensormap_and_ringbuffer/spmd_basic/test_spmd_basic.py
  • tests/st/a5/tensormap_and_ringbuffer/spmd_sync_start_edge/test_spmd_sync_start_edge.py
  • tests/st/a5/tensormap_and_ringbuffer/orch_so_cache/test_orch_so_cache.py
  • tests/st/a2a3/tensormap_and_ringbuffer/spmd_paged_attention_highperf/test_spmd_paged_attention_highperf.py
  • tests/st/a5/tensormap_and_ringbuffer/dfx/dep_gen/test_dep_gen.py
  • examples/a5/tensormap_and_ringbuffer/paged_attention_unroll_manual_scope/test_paged_attention_unroll.py
  • tests/st/task_timing/task_timing_slots/test_task_timing_e2e.py
  • tests/st/a2a3/host_build_graph/dfx/dep_gen/test_dep_gen.py
  • examples/a5/tensormap_and_ringbuffer/paged_attention/test_paged_attention.py
  • tests/st/a2a3/tensormap_and_ringbuffer/spmd_multiblock_aiv/test_spmd_multiblock_aiv.py
  • tests/st/a2a3/tensormap_and_ringbuffer/orch_so_cache/test_orch_so_cache.py
  • tests/st/a2a3/tensormap_and_ringbuffer/fanin_lookup_perf/test_fanin_lookup_perf.py
  • tests/st/a2a3/tensormap_and_ringbuffer/spmd_paged_attention/test_spmd_paged_attention.py
  • tests/st/a2a3/tensormap_and_ringbuffer/dynamic_register/test_dynamic_register.py
  • tests/st/a2a3/tensormap_and_ringbuffer/batch_paged_attention/test_batch_paged_attention.py
  • tests/st/a2a3/tensormap_and_ringbuffer/prepared_callable/test_prepared_callable.py

Comment thread src/a2a3/platform/onboard/host/device_runner.cpp Outdated
Comment thread src/a2a3/platform/sim/host/device_runner.cpp
Comment thread src/a5/platform/onboard/host/device_runner.cpp Outdated
Comment thread src/a5/platform/sim/host/device_runner.cpp
Comment thread src/common/platform/onboard/host/device_runner_base.cpp

@sunkaixuan2018 sunkaixuan2018 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The auto/partial-good direction is useful, but I think a few issues need to be addressed or clarified:

  1. The a5 usable count is not the device-visible AICPU pool.
    The host probe reads host-side OCCUPY=0x1fe and obtains 8 CPUs, while the documented device-side pool is 0x1f8 with only 6 schedulable CPUs. Although the default active count is 5, aicpu_launch_count is still set to 8. The existing hardware documentation states that launching more than the device-side OCCUPY popcount can stall the production affinity gate and lead to a timeout. Both the active count and launch count should be derived from the actual device-visible pool.

  2. The thread-count and CPU-selection policy should consider cluster affinity.
    resolve_aicpu_thread_num() currently only uses the total number of usable CPUs. Under PG, the remaining CPUs may be distributed across multiple clusters. For example, if four CPUs remain in a 2+2 distribution, the resolver still selects four threads and the affinity selector falls back to a cross-cluster layout. This may reintroduce the NUMA-crossing performance regression addressed by #1045/#1119.

    I suggest evaluating this on the current CPU architecture by marking different CPU cores as unavailable to emulate representative PG layouts, such as CPUs concentrated in one cluster or distributed across multiple clusters. Performance tests can then be used to compare different thread counts and placements and determine the best policy for each scenario—for example, whether keeping Scheduler threads, and preferably the orchestrator, in the same cluster is better than using more threads across clusters. The deterministic selector and tests from #1119 can be used as a reference. If a complete topology-aware policy is too complex for this PR, it would be reasonable to document the limitation and optimize it in a follow-up PR.

  3. The new a5 failure path leaks the AICore register buffer.
    init_aicore_register_addresses() allocates kernel_args_.args.regs before topology resolution, but regs_cleanup is created only afterwards. Returns caused by probe failure, usable < 2, or affinity-selection failure therefore skip cleanup. The guard should be installed before the allocation, as in the a2a3 implementation, or topology resolution should happen before allocating the buffer.

  4. aicpu_thread_num=1 is accepted but is not a valid normal-run configuration.
    On a5 onboard it skips topology setup, after which the device kernel rejects the missing affinity inputs. In the tensormap runtime it also means one orchestrator and zero schedulers. The public configuration should probably accept only 0 (auto) or [2, MAX]; any internal one-thread initialization path should be kept separate.

  5. The core PG behavior needs deterministic tests.
    The current test changes mainly remove explicit thread counts and exercise the healthy auto path indirectly. Please add host-side tests for usable < default, usable < 2, explicit values larger than usable, aicpu_thread_num=1, and PG layouts distributed across multiple clusters. The tests should also verify that the resolved active count, selected CPUs, Runtime metadata, DFX counts, and actual launch count remain consistent.

There are also several user-facing documents that still list the default as 3, and the generic “1 orchestrator + N schedulers” wording does not match host_build_graph, where the device-side thread roles differ.

@yanghaoran29

Copy link
Copy Markdown
Contributor Author

Implemented the initial topology-local auto policy and addressed the actionable review findings:

  • On a2a3, aicpu_thread_num=0 now selects all usable CPUs from the cluster with the highest usable count. Ties prefer the higher cluster ID.
  • On a5, auto mode selects all usable CPUs from the die with the highest usable count. Ties prefer the higher die ID. On the observed healthy topology this resolves to four active threads on one die instead of five threads spanning dies.
  • The a5 host topology reconstruction now excludes the SMT physical core reserved by the AICPU OS, so the reconstructed user pool and launch count match the six-CPU device-visible pool on the observed SKU rather than host OCCUPY=0x1fe.
  • Effective active counts are published consistently to Runtime and the local launch/DFX setup state.
  • Public normal-run validation now accepts only 0 (auto) or [2, MAX]; 1 is rejected.
  • The a5 register-buffer cleanup guard is installed immediately before allocation, covering topology and affinity failure returns.
  • Added deterministic host-side tests for normal layouts, uneven PG layouts, equal-size tie-breaking, and insufficient per-cluster/per-die capacity on both architectures.
  • Updated the architecture documentation for the new auto semantics.

Local validation:

  • editable platform/runtime rebuild: passed
  • Python worker UT: 26 passed
  • C++ no-hardware UT: 67 passed
  • topology selection UT after formatting: 2/2 passed
  • pre-commit: all code/style hooks passed; the pyright hook could not download pyright@1.1.407 because this environment's npm access returned HTTP 403

The full sim run was also attempted, but concurrent a2a3sim/a5sim execution caused shared simpler_log_init failures in the local environment; this was an environment-level initialization conflict rather than a topology assertion failure. CI will run the architectures in their isolated jobs.

@yanghaoran29
yanghaoran29 marked this pull request as draft July 30, 2026 07:08
@yanghaoran29 yanghaoran29 reopened this Jul 31, 2026
@yanghaoran29 yanghaoran29 changed the title Add: partial-good-aware AICPU thread resolution (a2a3/a5) Add: automatic AICPU architecture defaults (a2a3/a5) Aug 3, 2026
@yanghaoran29
yanghaoran29 marked this pull request as ready for review August 3, 2026 02:16
@yanghaoran29
yanghaoran29 force-pushed the aicpu-pg-a2a3-a5 branch 3 times, most recently from 192e61c to 69480d6 Compare August 3, 2026 06:04
@ChaoZheng109

Copy link
Copy Markdown
Collaborator

Review 总结(/review-pr)

核心逻辑正确、CI 全绿(含 st-onboard-a2a3 / st-onboard-a5),0 = auto 哨兵设计合理。主要问题集中在 文档一致性:本 PR 把默认值 3 → 0 并删除了一批示例/测试里的 aicpu_thread_num 配置,但未按 .claude/rules/doc-consistency.md §1(改动前后回扫引用)/ §3(referent 消失即删)回扫文档,留下多处漂移。建议在同一提交内补齐。

🔴 Must fix —— 文档仍把默认值写成 3(现为 0,事实错误)

文件 内容
docs/capability-survey.md:66 "aicpu_thread_num is 3 (call_config.h:112)" —— 还精确引了行号
docs/task-flow.md:213 int32_t aicpu_thread_num = 3;
docs/user/reference/python-api.md:123 面向用户的 API 表默认列写 3
docs/chip-level-arch.md:151 config.aicpu_thread_num = 3
docs/getting-started.md:217 "aicpu_thread_num": 3,
docs/task-flow.md:686 CallConfig(aicpu_thread_num=3)

🟠 Should fix —— 示例 README 仍描述已被本 PR 删除的 per-case 配置

对应目录的 test CASES 里 "config": {"aicpu_thread_num": 4} 已删,README 描述未同步:

  • examples/a2a3/tensormap_and_ringbuffer/scalar_data/README.md:52
  • examples/a2a3/tensormap_and_ringbuffer/paged_attention/README.md:24
  • examples/a2a3/tensormap_and_ringbuffer/paged_attention_unroll_manual_scope/README.md:48

说明:a2a3 auto→4,实际线程数不变,数字 "4" 不算错;错在把它描述成"该 case 显式设置的配置项",而该配置项已被删除。

🟡 a5 hardware.md 范围表述

src/a5/docs/hardware.md:142 标注显式范围 [2, 7],但 onboard 实际上限为设备可见池的 6(显式传 7 能过 validate 却会在 compute_allowed_cpus 阶段运行时报错)。虽有"onboard requires the device-visible pool to fit"兜底,但 [2,7] 仍可能误导,建议点明"编译期上限 7 / onboard 有效上限 6"。

可留(非漂移)

dfx 三处 min(aicpu_thread_num, kMaxCollectorThreads)、各 RUNTIME_LOGIC.md 的 "With aicpu_thread_num=4"、remote-l3 protocol.md wire 字段、l3 workers README 的 "=2 required" —— 描述运行时行为或仍有效的显式用法,不受默认值变更影响。docs/testing.md:606docs/user/how-to/write-and-run-a-kernel.md:58 里的 "config": {"aicpu_thread_num": 4} 是演示"可以这样设"的机制示例,合法,可留(改成 auto 更贴合新默认)。


背景记录(已与 reviewer 讨论,本 PR 不处理)

  • a2a3 用 resolve_aicpu_thread_num 做部分良品钳制、a5 用严格匹配,二者不对称:源于两 arch 选核策略不同(a5 compute_allowed_cpus 按 SMT/物理拓扑分组,a2a3 按 cluster 扁平分组)。后续会统一更新选核策略,此处有意保留不对称。建议在 a5 run() 加一行注释说明"为何不复用 common base 里的 resolve_aicpu_thread_num",否则该 helper 放在公共基类却只被 a2a3 调用,读者易误判为遗漏。
  • resolve_aicpu_thread_num 的降级分支(usable < 2 报错 / total < desired 告警)暂不补测试:随后续选核策略更新一并处理。
  • aicpu_thread_num 未像 block_dim(Refactor: remove the user-facing block_dim knob #1309)那样彻底删旋钮:合理——block_dim 只有唯一正确值(整设备),而 aicpu_thread_num 有真实非默认需求(如 examples/workers/l3/* 的 serving loop 要求 = 2)。建议在 CallConfig 注释里点明"因 L3 等场景需要而保留显式覆盖",以免读者误以为是过渡态。

Verdict

Approve(建议补文档) —— 逻辑与硬件验证均通过,阻塞项仅为上述文档一致性,建议随本 PR 一并修 🔴/🟠 两档。

Use zero as the default AICPU thread sentinel while preserving explicit
per-run overrides.

- Resolve auto to four active threads on a2a3 and five on a5.
- Keep affinity, launch, Runtime, and DFX state consistent with the
  effective thread count.
- Resolve simulation defaults directly without hardware topology probing.
- Reject one-thread normal runs and align the a5 host-visible launch pool
  with device availability.
- Align public references and example descriptions with auto selection and
  document the a5 onboard pool limit.
@yanghaoran29

Copy link
Copy Markdown
Contributor Author

@ChaoZheng109 Addressed the documentation consistency findings:

  • Updated all six stale public/default examples from 3 to 0 (auto).
  • Updated the three example READMEs so they describe automatic AICPU selection rather than removed per-case aicpu_thread_num: 4 settings.
  • Clarified that a5 accepts explicit values through the compile-time limit of 7, while the observed onboard device-visible pool limits the effective maximum to 6.

The documentation-only changes pass the full local pre-commit suite, including markdownlint.

@ChaoZheng109
ChaoZheng109 merged commit 91da523 into hw-native-sys:main Aug 3, 2026
18 checks passed
ChaoWao added a commit to ChaoWao/simpler-fork that referenced this pull request Aug 3, 2026
hw-native-sys#1587 moved three contracts without moving the text that described them, and
left one failure mode expressed as a noexcept violation.

Geometry. resolve_block_dim() and prepare_launch_shape() no longer write
block_dim_ or worker_count_; activate_launch_shape() latches both on the
executor thread immediately before run(). The comment and the LOG_ERROR in
each onboard run() still named prepare_launch_shape, so the one diagnostic a
future reader greps pointed at a function that latches nothing. hw-native-sys#1521 later
edited the line directly below that comment and left it standing, which is
how a stale comment survives. The simulation runners keep their wording:
SimDeviceRunnerBase::prepare_launch_shape does still assign block_dim_.

Streams. RunStreamSlots became a two-thread class when native prepare started
provisioning the successor's slot while the executor retires the
predecessor's. Per-slot handles are safe — admission gives each slot one
owner — but created_count_ is shared across owners and is also read from an
unrelated thread through get_run_stream_set_create_count, so it is now
atomic and the ownership rule is stated on the class.

Thread selection. restore_native_run_thread_selection was noexcept while
run_selection() could throw: on a thread created by create_thread the
per-thread block does not exist yet, so installation allocates. Split out a
non-throwing try_run_selection() and let restore abort with a message on the
unrecoverable path. Returning instead would leave the thread on the default
slot and bank, addressing storage another lease owns, and a freshly started
thread has no channel to report the failure through. B6c removes the
mechanism outright; until then the failure is diagnosable rather than a bare
terminate.

Symbol loading. Since every required pipeline symbol became a strict load,
the dominant cause of a dlsym failure is a host runtime out of sync with the
tree that consumes it. Say so in the error, which otherwise reports only the
missing name.

Also spell the successor-already-staged test as occupied > 1, since the loop
above it has already rejected every predecessor that may not carry one, and
record that simulation discards native-run identity by design.
@yanghaoran29
yanghaoran29 deleted the aicpu-pg-a2a3-a5 branch August 3, 2026 09:22
ChaoWao added a commit that referenced this pull request Aug 3, 2026
)

#1587 moved three contracts without moving the text that described them, and
left one failure mode expressed as a noexcept violation.

Geometry. resolve_block_dim() and prepare_launch_shape() no longer write
block_dim_ or worker_count_; activate_launch_shape() latches both on the
executor thread immediately before run(). The comment and the LOG_ERROR in
each onboard run() still named prepare_launch_shape, so the one diagnostic a
future reader greps pointed at a function that latches nothing. #1521 later
edited the line directly below that comment and left it standing, which is
how a stale comment survives. The simulation runners keep their wording:
SimDeviceRunnerBase::prepare_launch_shape does still assign block_dim_.

Streams. RunStreamSlots became a two-thread class when native prepare started
provisioning the successor's slot while the executor retires the
predecessor's. Per-slot handles are safe — admission gives each slot one
owner — but created_count_ is shared across owners and is also read from an
unrelated thread through get_run_stream_set_create_count, so it is now
atomic and the ownership rule is stated on the class.

Thread selection. restore_native_run_thread_selection was noexcept while
run_selection() could throw: on a thread created by create_thread the
per-thread block does not exist yet, so installation allocates. Split out a
non-throwing try_run_selection() and let restore abort with a message on the
unrecoverable path. Returning instead would leave the thread on the default
slot and bank, addressing storage another lease owns, and a freshly started
thread has no channel to report the failure through. B6c removes the
mechanism outright; until then the failure is diagnosable rather than a bare
terminate.

Symbol loading. Since every required pipeline symbol became a strict load,
the dominant cause of a dlsym failure is a host runtime out of sync with the
tree that consumes it. Say so in the error, which otherwise reports only the
missing name.

Also spell the successor-already-staged test as occupied > 1, since the loop
above it has already rejected every predecessor that may not carry one, and
record that simulation discards native-run identity by design.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants